#if defined(__linux__)
#define CLOSE_SOCKET close
#elif defined(_WIN32) || defined(_WIN64)
#define CLOSE_SOCKET closesocket
#endif

#include "HttpClient.h"
#include "./common/YXConstant.h"
#include "./common/YXLog.h"
#include "./common/YXTime.h"
#include "HttpRequest.h"
#include "HttpResponse.h"
#include "Server.h"

#include <stdlib.h>
#include <unistd.h>

ClientList *client_list_create() {
    ClientList *list = malloc(sizeof(ClientList));
    list->head       = malloc(sizeof(Client));
    list->head->prev = list->head;
    list->head->next = list->head;
    list->size       = 0;

    return list;
}

void client_list_add(ClientList *list, Client *client) {
    client->prev           = list->head->prev;
    client->next           = list->head;
    list->head->prev->next = client;
    list->head->prev       = client;
    list->size++;
}

void client_list_remove(ClientList *list, Client *client) {
    client->prev->next = client->next;
    client->next->prev = client->prev;
    list->size--;
}

ClientListIterator *client_list_iterator_create(ClientList *list) {
    ClientListIterator *iter = malloc(sizeof(ClientListIterator));
    iter->client_list        = list;
    iter->client             = list->head->next;
    return iter;
}

Client *client_list_iterator_next(ClientListIterator *iter) {
    if (iter->client == iter->client_list->head)
        return NULL;
    Client *client = iter->client;
    iter->client   = iter->client->next;
    return client;
}

void client_list_iterator_reset(ClientListIterator *iter) { iter->client = iter->client_list->head->next; }

Client *create_client(int client_fd) {
    // 设置非阻塞
    if (net_set_non_block(client_fd) == YX_ERR) {
        logErrno();
        CLOSE_SOCKET(client_fd);
        return NULL;
    }

    Client *client = malloc(sizeof(Client));

    // 添加文件事件
    if (net_create_file_event(server.el, client_fd, YX_NET_READABLE, read_reqeust, client) == YX_ERR) {
        logErrno();
        CLOSE_SOCKET(client_fd);
        free(client);
        return NULL;
    }

    client->auth           = 0;
    client->fd             = client_fd;
    client->bufpos         = 0;
    client->input_buffer   = sds_create_empty(HTTP_TEMP_INPUT_BUFFER_SIZE);
    client->request        = create_request();
    client->response       = create_response();
    client->last_send_time = mstime();
    client_list_add(server.client_list, client);
    set_client_is_connected(client);

    return client;
}

void reset_client(Client *client) {
    net_create_file_event(server.el, client->fd, YX_NET_READABLE, read_reqeust, client);
    client->bufpos = 0;
    sds_clear(client->input_buffer);
    reset_request(client->request);
    reset_response(client->response);
    set_client_is_connected(client);
}

void set_client_is_connected(Client *client) { server.client_status[client->fd] = CLIENT_STATUS_CONNECTED; }

/**
 * 将 client 的状态设为 busy,
 * 主要防止 client 被进行超时回收
 */
void set_client_is_busy(Client *client) { server.client_status[client->fd] = CLIENT_STATUS_BUSY; }

void set_client_is_closed(Client *client) { server.client_status[client->fd] = CLIENT_STATUS_DISCONNECTED; }

int client_get_status(Client *client) { return server.client_status[client->fd]; }

/**
 * 主要用于子线程中, 安全清理客户端的部分资源（剩余资源由主线程进行清理）
 */
void client_safe_free(Client *client) {
    int fd     = client->fd;
    client->fd = -1;
    net_delete_file_event(server.el, fd, server.el->events[fd].mask);
    server.client_status[fd] = CLIENT_STATUS_DISCONNECTED;
    CLOSE_SOCKET(fd);
    logDebug("A client closed connection");
}

void client_remain_free(Client *client) {
    client_list_remove(server.client_list, client);
    sds_free(client->input_buffer);
    free_request(client->request);
    free_response(client->response);
    free(client);
}

void client_full_free(Client *client) {
    client_safe_free(client);
    client_remain_free(client);
}
